<template>
  <div class="audio-processor">
    <!-- 音频上传区域 -->
    <el-card class="upload-card" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>音频上传</span>
        </div>
      </template>
      <el-upload
        class="upload-demo"
        drag
        :auto-upload="false"
        :on-change="handleFileChange"
        :file-list="fileList"
        accept="audio/*"
        :limit="1"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          将音频文件拖到此处，或<em>点击上传</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            支持 MP3、WAV、M4A 等音频格式
          </div>
        </template>
      </el-upload>
    </el-card>

    <!-- 音频播放和参数设置 -->
    <el-card v-if="audioFile" class="control-card" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>音频控制</span>
        </div>
      </template>
      
      <!-- 原始音频播放器 -->
      <div class="audio-player">
        <h4>原始音频：</h4>
        <audio ref="audioElement" :src="audioUrl" controls preload="metadata"></audio>
      </div>

      <!-- 参数设置 -->
      <el-row :gutter="20" class="params-row">
        <el-col :span="12">
          <div class="param-item">
            <label>目标分段数量：</label>
            <el-input-number
              v-model="targetSegments"
              :min="2"
              :max="200"
              size="large"
            />
          </div>
        </el-col>
        <el-col :span="12">
          <div class="param-item">
            <label>静音阈值（dB）：</label>
            <el-input-number
              v-model="silenceThreshold"
              :min="-60"
              :max="-10"
              :step="1"
              size="large"
            />
          </div>
        </el-col>
      </el-row>

      <el-row :gutter="20" class="params-row">
        <el-col :span="12">
          <div class="param-item">
            <label>最小静音时长（ms）：</label>
            <el-input-number
              v-model="minSilenceDuration"
              :min="100"
              :max="5000"
              :step="100"
              size="large"
            />
          </div>
        </el-col>
        <el-col :span="12">
          <div class="param-item">
            <label>保护边距（ms）：</label>
            <el-input-number
              v-model="protectionMargin"
              :min="50"
              :max="1000"
              :step="50"
              size="large"
            />
          </div>
        </el-col>
      </el-row>

      <!-- 控制按钮 -->
      <div class="action-buttons">
        <el-button 
          type="primary" 
          size="large" 
          @click="startProcessing"
          :loading="processing"
          :disabled="!audioFile"
        >
          <el-icon><video-play /></el-icon>
          开始分段处理
        </el-button>
        <el-button 
          type="warning" 
          size="large" 
          @click="resetAll"
          :disabled="processing"
        >
          <el-icon><refresh-right /></el-icon>
          重置
        </el-button>
      </div>
    </el-card>

    <!-- 处理进度 -->
    <el-card v-if="processing || processed" class="progress-card" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>处理进度</span>
        </div>
      </template>
      <el-progress 
        :percentage="progressPercentage" 
        :status="processing ? 'success' : 'success'"
        :stroke-width="20"
      />
      <div class="progress-text">{{ progressText }}</div>
    </el-card>

    <!-- 静音分析结果 -->
    <el-card v-if="silenceSegments.length > 0" class="analysis-card" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>静音分析结果</span>
        </div>
      </template>
      <div class="silence-info">
        <p>检测到 <strong>{{ silenceSegments.length }}</strong> 个静音段</p>
        <p>将选择前 <strong>{{ targetSegments - 1 }}</strong> 个最长的静音段进行分割</p>
      </div>
      <el-table :data="silenceSegments" style="width: 100%" max-height="200">
        <el-table-column prop="index" label="序号" width="80" />
        <el-table-column prop="start" label="开始时间(s)" width="120">
          <template #default="scope">
            {{ (scope.row.start / 1000).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="end" label="结束时间(s)" width="120">
          <template #default="scope">
            {{ (scope.row.end / 1000).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="duration" label="时长(s)" width="100">
          <template #default="scope">
            {{ (scope.row.duration / 1000).toFixed(2) }}
          </template>
        </el-table-column>
        <el-table-column prop="selected" label="是否选中" width="100">
          <template #default="scope">
            <el-tag :type="scope.row.selected ? 'success' : ''">
              {{ scope.row.selected ? '选中' : '未选中' }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 分段结果 -->
    <el-card v-if="audioSegments.length > 0" class="segments-card" shadow="hover">
      <template #header>
        <div class="card-header">
          <span>音频分段结果</span>
          <el-button type="primary" size="small" @click="downloadAllSegments">
            <el-icon><download /></el-icon>
            下载所有分段
          </el-button>
        </div>
      </template>
      <el-row :gutter="16">
        <el-col :span="8" v-for="(segment, index) in audioSegments" :key="index">
          <el-card class="segment-item" shadow="hover">
            <div class="segment-header">
              <h4>分段 {{ index + 1 }}</h4>
              <el-button 
                type="primary" 
                size="small" 
                @click="downloadSegment(segment, index)"
              >
                <el-icon><download /></el-icon>
                下载
              </el-button>
            </div>
            <div class="segment-info">
              <p>时长: {{ (segment.duration / 1000).toFixed(2) }}s</p>
              <p>开始: {{ (segment.start / 1000).toFixed(2) }}s</p>
              <p>结束: {{ (segment.end / 1000).toFixed(2) }}s</p>
            </div>
            <audio :src="segment.url" controls class="segment-audio"></audio>
          </el-card>
        </el-col>
      </el-row>
    </el-card>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { UploadFilled, VideoPlay, RefreshRight, Download } from '@element-plus/icons-vue'

// 响应式数据
const audioFile = ref(null)
const audioUrl = ref('')
const audioElement = ref(null)
const fileList = ref([])
const processing = ref(false)
const processed = ref(false)
const progressPercentage = ref(0)
const progressText = ref('')

// 参数设置
const targetSegments = ref(4)
const silenceThreshold = ref(-30) // dB
const minSilenceDuration = ref(500) // ms
const protectionMargin = ref(200) // ms

// 分析结果
const silenceSegments = ref([])
const audioSegments = ref([])

// 音频上下文
let audioContext = null
let audioBuffer = null

// 处理文件上传
const handleFileChange = (file) => {
  if (file.raw) {
    audioFile.value = file.raw
    audioUrl.value = URL.createObjectURL(file.raw)
    fileList.value = [file]
    resetProcessingState()
  }
}

// 重置处理状态
const resetProcessingState = () => {
  processing.value = false
  processed.value = false
  progressPercentage.value = 0
  progressText.value = ''
  silenceSegments.value = []
  audioSegments.value = []
}

// 重置所有
const resetAll = () => {
  audioFile.value = null
  audioUrl.value = ''
  fileList.value = []
  resetProcessingState()
}

// 开始处理
const startProcessing = async () => {
  if (!audioFile.value) {
    ElMessage.error('请先上传音频文件')
    return
  }

  processing.value = true
  processed.value = false
  progressPercentage.value = 0
  progressText.value = '正在初始化音频处理...'

  try {
    // 初始化 Web Audio API
    if (!audioContext) {
      audioContext = new (window.AudioContext || window.webkitAudioContext)()
    }

    // 读取音频文件
    progressText.value = '正在读取音频文件...'
    progressPercentage.value = 10
    
    const arrayBuffer = await audioFile.value.arrayBuffer()
    
    progressText.value = '正在解码音频...'
    progressPercentage.value = 20
    
    audioBuffer = await audioContext.decodeAudioData(arrayBuffer)
    
    // 分析静音段
    progressText.value = '正在分析静音段...'
    progressPercentage.value = 40
    
    const silences = await analyzeSilence(audioBuffer)
    
    // 尝试创建分段（带自动重试机制）
    const result = await createSegmentsWithRetry(audioBuffer, silences)
    audioSegments.value = result.segments
    silenceSegments.value = result.silenceInfo
    
    progressText.value = '处理完成！'
    progressPercentage.value = 100
    processed.value = true
    
    if (result.retried) {
      ElMessage.success({
        message: `智能调整成功！目标 ${targetSegments.value} 个分段，实际创建了 ${result.segments.length} 个`,
        duration: 5000
      })
    } else {
      const message = result.segments.length === targetSegments.value 
        ? `完美达成目标！成功创建了 ${result.segments.length} 个音频分段`
        : `成功创建了 ${result.segments.length} 个音频分段（目标：${targetSegments.value}个）`
      ElMessage.success(message)
    }
    
  } catch (error) {
    console.error('处理音频时出错:', error)
    ElMessage.error('处理音频时出错: ' + error.message)
  } finally {
    processing.value = false
  }
}

// 创建分段（带自动重试机制）
const createSegmentsWithRetry = async (audioBuffer, silences) => {
  const originalTarget = targetSegments.value
  
  // 第一次尝试
  progressText.value = '正在选择分割点...'
  progressPercentage.value = 60
  
  let selectedSilences = selectSilenceSegments(silences)
  let silenceInfo = silences.map((silence, index) => ({
    index: index + 1,
    start: silence.start,
    end: silence.end,
    duration: silence.end - silence.start,
    selected: selectedSilences.includes(silence)
  }))
  
  progressText.value = '正在创建音频分段...'
  progressPercentage.value = 80
  
  let segments = await createAudioSegments(audioBuffer, selectedSilences)
  
  // 检查是否需要重试
  const shouldRetry = segments.length === originalTarget - 1 && segments.length > 0
  
  if (shouldRetry) {
    console.log(`分段数量 ${segments.length} 比目标 ${originalTarget} 少1个，尝试自动调整...`)
    
    // 临时增加目标分段数量
    targetSegments.value = originalTarget + 1
    
    progressText.value = '自动调整中，重新选择分割点...'
    progressPercentage.value = 65
    
    // 重新选择分割点
    selectedSilences = selectSilenceSegments(silences)
    silenceInfo = silences.map((silence, index) => ({
      index: index + 1,
      start: silence.start,
      end: silence.end,
      duration: silence.end - silence.start,
      selected: selectedSilences.includes(silence)
    }))
    
    progressText.value = '重新创建音频分段...'
    progressPercentage.value = 85
    
    // 重新创建分段
    const retrySegments = await createAudioSegments(audioBuffer, selectedSilences)
    
    // 恢复原始目标值
    targetSegments.value = originalTarget
    
    // 如果重试后分段数量更接近目标，使用重试结果
    if (Math.abs(retrySegments.length - originalTarget) <= Math.abs(segments.length - originalTarget)) {
      console.log(`重试成功！调整后创建了 ${retrySegments.length} 个分段`)
      return {
        segments: retrySegments,
        silenceInfo: silenceInfo,
        retried: true
      }
    } else {
      console.log(`重试后效果不佳，使用原始结果`)
    }
  }
  
  return {
    segments: segments,
    silenceInfo: silenceInfo,
    retried: false
  }
}

// 分析静音段
const analyzeSilence = async (buffer) => {
  const channelData = buffer.getChannelData(0) // 使用第一个声道
  const sampleRate = buffer.sampleRate
  const silences = []
  
  let silenceStart = -1
  let currentTime = 0
  
  // 分析每个样本
  for (let i = 0; i < channelData.length; i++) {
    const sample = Math.abs(channelData[i])
    const dbValue = 20 * Math.log10(sample + 1e-10) // 避免log(0)
    
    currentTime = (i / sampleRate) * 1000 // 转换为毫秒
    
    if (dbValue < silenceThreshold.value) {
      // 检测到静音
      if (silenceStart === -1) {
        silenceStart = currentTime
      }
    } else {
      // 检测到声音
      if (silenceStart !== -1) {
        const silenceDuration = currentTime - silenceStart
        if (silenceDuration >= minSilenceDuration.value) {
          silences.push({
            start: silenceStart,
            end: currentTime,
            duration: silenceDuration
          })
        }
        silenceStart = -1
      }
    }
  }
  
  // 处理音频结尾的静音
  if (silenceStart !== -1) {
    const silenceDuration = currentTime - silenceStart
    if (silenceDuration >= minSilenceDuration.value) {
      silences.push({
        start: silenceStart,
        end: currentTime,
        duration: silenceDuration
      })
    }
  }
  
  return silences
}

// 选择静音段进行分割
const selectSilenceSegments = (silences) => {
  // 过滤掉太短的静音段（小于两倍保护边距的静音段无法安全分割）
  const minRequiredDuration = protectionMargin.value * 2
  const validSilences = silences.filter(silence => silence.duration >= minRequiredDuration)
  
  // 按持续时间降序排序
  const sortedSilences = [...validSilences].sort((a, b) => b.duration - a.duration)
  
  // 选择前 (targetSegments - 1) 个最长的静音段
  const selectedCount = Math.min(targetSegments.value - 1, sortedSilences.length)
  const selected = sortedSilences.slice(0, selectedCount)
  
  if (selected.length < targetSegments.value - 1) {
    console.warn(`只找到 ${selected.length} 个可用的静音段，无法创建 ${targetSegments.value} 个分段`)
  }
  
  // 按时间顺序重新排序
  return selected.sort((a, b) => a.start - b.start)
}

// 创建音频分段
const createAudioSegments = async (buffer, selectedSilences) => {
  const segments = []
  const duration = buffer.duration * 1000 // 转换为毫秒
  
  let segmentStart = 0
  
  for (const silence of selectedSilences) {
    // 计算分割点
    let cutStart = silence.start + protectionMargin.value
    let cutEnd = silence.end - protectionMargin.value
    
    // 如果是音频末尾的静音，只在开始处加保护边距
    if (silence.end >= duration - 100) { // 接近音频结尾
      cutEnd = silence.end
    }
    
    // 确保分割点有效 - 修复：防止cutStart >= cutEnd的情况
    if (cutStart >= cutEnd) {
      // 如果静音段太短，跳过这个静音段，不进行分割
      console.warn(`静音段太短，跳过分割: ${silence.start}ms - ${silence.end}ms`)
      continue
    }
    
    // 确保分割点有效且大于当前分段开始位置
    if (cutStart > segmentStart) {
      // 创建分段 - 检查分段时长
      const segmentEnd = cutStart
      const segmentDuration = segmentEnd - segmentStart
      const minSegmentDuration = 100 // 最小分段时长100ms
      
      if (segmentDuration >= minSegmentDuration) {
        const segment = await extractAudioSegment(buffer, segmentStart, segmentEnd)
        segments.push(segment)
      } else {
        console.warn(`分段太短，跳过: ${segmentStart}ms - ${segmentEnd}ms (时长: ${segmentDuration.toFixed(2)}ms)`)
      }
      
      segmentStart = cutEnd
    }
  }
  
  // 添加最后一个分段
  if (segmentStart < duration) {
    const finalSegmentDuration = duration - segmentStart
    const minSegmentDuration = 100 // 最小分段时长100ms
    
    if (finalSegmentDuration >= minSegmentDuration) {
      const segment = await extractAudioSegment(buffer, segmentStart, duration)
      segments.push(segment)
    } else {
      console.warn(`最后分段太短，跳过: ${segmentStart}ms - ${duration}ms (时长: ${finalSegmentDuration.toFixed(2)}ms)`)
    }
  }
  
  return segments
}

// 提取音频分段
const extractAudioSegment = async (buffer, startTime, endTime) => {
  // 安全检查：确保时间参数有效
  const minDuration = 100 // 最小分段时长100ms，与createAudioSegments保持一致
  const duration = endTime - startTime
  
  if (duration < minDuration) {
    console.error(`分段时长太短: startTime=${startTime}ms, endTime=${endTime}ms, duration=${duration}ms`)
    throw new Error(`分段时长必须大于等于${minDuration}ms，当前时长: ${duration.toFixed(2)}ms`)
  }
  
  const sampleRate = buffer.sampleRate
  const startSample = Math.floor((startTime / 1000) * sampleRate)
  const endSample = Math.floor((endTime / 1000) * sampleRate)
  const segmentLength = endSample - startSample
  
  // 确保分段长度大于0
  if (segmentLength <= 0) {
    console.error(`分段长度无效: ${segmentLength} samples`)
    throw new Error(`分段长度必须大于0: ${segmentLength} samples`)
  }
  
  // 创建新的 AudioBuffer
  const segmentBuffer = audioContext.createBuffer(
    buffer.numberOfChannels,
    segmentLength,
    sampleRate
  )
  
  // 复制音频数据
  for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
    const channelData = buffer.getChannelData(channel)
    const segmentChannelData = segmentBuffer.getChannelData(channel)
    
    for (let i = 0; i < segmentLength; i++) {
      segmentChannelData[i] = channelData[startSample + i] || 0
    }
  }
  
  // 转换为 WAV 格式
  const wavBlob = audioBufferToWav(segmentBuffer)
  const url = URL.createObjectURL(wavBlob)
  
  return {
    start: startTime,
    end: endTime,
    duration: endTime - startTime,
    url: url,
    blob: wavBlob
  }
}

// 将 AudioBuffer 转换为 WAV 格式
const audioBufferToWav = (buffer) => {
  const length = buffer.length
  const numberOfChannels = buffer.numberOfChannels
  const sampleRate = buffer.sampleRate
  const bytesPerSample = 2
  const byteRate = sampleRate * numberOfChannels * bytesPerSample
  const blockAlign = numberOfChannels * bytesPerSample
  const dataSize = length * numberOfChannels * bytesPerSample
  const bufferSize = 44 + dataSize
  
  const arrayBuffer = new ArrayBuffer(bufferSize)
  const view = new DataView(arrayBuffer)
  
  // WAV 文件头
  const writeString = (offset, string) => {
    for (let i = 0; i < string.length; i++) {
      view.setUint8(offset + i, string.charCodeAt(i))
    }
  }
  
  writeString(0, 'RIFF')
  view.setUint32(4, bufferSize - 8, true)
  writeString(8, 'WAVE')
  writeString(12, 'fmt ')
  view.setUint32(16, 16, true) // PCM format
  view.setUint16(20, 1, true) // PCM
  view.setUint16(22, numberOfChannels, true)
  view.setUint32(24, sampleRate, true)
  view.setUint32(28, byteRate, true)
  view.setUint16(32, blockAlign, true)
  view.setUint16(34, bytesPerSample * 8, true)
  writeString(36, 'data')
  view.setUint32(40, dataSize, true)
  
  // 音频数据
  let offset = 44
  for (let i = 0; i < length; i++) {
    for (let channel = 0; channel < numberOfChannels; channel++) {
      const sample = Math.max(-1, Math.min(1, buffer.getChannelData(channel)[i]))
      view.setInt16(offset, sample * 0x7FFF, true)
      offset += 2
    }
  }
  
  return new Blob([arrayBuffer], { type: 'audio/wav' })
}

// 下载单个分段
const downloadSegment = (segment, index) => {
  const a = document.createElement('a')
  a.href = segment.url
  a.download = `音频分段_${index + 1}.wav`
  a.click()
}

// 下载所有分段
const downloadAllSegments = () => {
  audioSegments.value.forEach((segment, index) => {
    setTimeout(() => {
      downloadSegment(segment, index)
    }, index * 100) // 延迟下载，避免浏览器阻止多个下载
  })
}

onMounted(() => {
  // 组件挂载时的初始化操作
})
</script>

<style scoped>
.audio-processor {
  max-width: 1200px;
  margin: 0 auto;
}

.upload-card,
.control-card,
.progress-card,
.analysis-card,
.segments-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: bold;
  font-size: 16px;
}

.upload-demo {
  margin: 20px 0;
}

.audio-player {
  margin-bottom: 20px;
  text-align: left;
}

.audio-player h4 {
  margin-bottom: 10px;
  color: #409eff;
}

.audio-player audio {
  width: 100%;
  margin-bottom: 10px;
}

.params-row {
  margin-bottom: 20px;
}

.param-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 0;
}

.param-item label {
  font-weight: bold;
  color: #606266;
  margin-right: 10px;
}

.action-buttons {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 20px;
}

.progress-text {
  margin-top: 10px;
  font-size: 14px;
  color: #606266;
}

.silence-info {
  text-align: left;
  margin-bottom: 15px;
  padding: 10px;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.segment-item {
  margin-bottom: 16px;
}

.segment-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.segment-header h4 {
  margin: 0;
  color: #409eff;
}

.segment-info {
  text-align: left;
  margin-bottom: 10px;
  font-size: 12px;
  color: #909399;
}

.segment-info p {
  margin: 4px 0;
}

.segment-audio {
  width: 100%;
  height: 30px;
}

:deep(.el-upload-dragger) {
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  box-sizing: border-box;
  width: 100%;
  height: 180px;
  text-align: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  background-color: #fafafa;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

:deep(.el-upload-dragger:hover) {
  border-color: #409eff;
}

:deep(.el-icon--upload) {
  font-size: 67px;
  color: #c0c4cc;
  margin-bottom: 16px;
}

:deep(.el-upload__text) {
  color: #606266;
  font-size: 14px;
  text-align: center;
}

:deep(.el-upload__tip) {
  font-size: 12px;
  color: #909399;
  margin-top: 7px;
}
</style>